package com.zrrd.service.impl;

import com.alibaba.druid.support.json.JSONUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zrrd.common.bo.RoleBo;
import com.zrrd.common.bo.RuleBo;
import com.zrrd.common.dto.LoginDto;
import com.zrrd.common.page.ManagerPageVo;
import com.zrrd.common.vo.ManagerLoginVo;
import com.zrrd.common.vo.ManagerVo;
import com.zrrd.entity.Manager;
import com.zrrd.entity.Role;
import com.zrrd.mapper.ManagerMapper;
import com.zrrd.service.ManagerService;
import com.zrrd.service.RoleService;
import com.zrrd.service.RuleService;
import com.zrrd.common.util.JwtUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author WanJl
 * @version 1.0
 * @title ManagerServiceImpl
 * @description 管理员用户服务层实现类
 * @create 2024/9/5
 */
@Service
public class ManagerServiceImpl extends ServiceImpl<ManagerMapper, Manager> implements ManagerService {

    @Resource
    private RoleService roleService;
    @Resource
    private RuleService ruleService;
    @Resource
    private RedisTemplate redisTemplate;
    /**
     * 管理员登录
     *
     * @param loginDto
     * @return
     */
    @Override
    public ManagerLoginVo login(LoginDto loginDto) {
        //1、根据【用户名】查询manager表的信息
        Manager manager = lambdaQuery().eq(Manager::getUsername, loginDto.getUsername()).one();//链式编程
        if (manager == null) return null;

        // List<Manager> list = list(); 查询管理员列表
        // save();  新增
        // updateById();  修改
        // removeById();  删除

        //2、判断用户名和密码是否一致，不一致直接return null
        //我们要对密码进行加密
        //采用一些不可逆的数学算法，生成新的内容
        //MD5
        String password = DigestUtils.md5DigestAsHex((loginDto.getPassword() + JwtUtils.generalKey()).getBytes());
        System.out.println("密码---------》"+password);

        //3、判断密码是否一致，如果一致，则登录成功，需要返回用户角色信息以及角色的权限列表
        if (manager.getPassword().equals(password)) {
            //4、把查询到的管理员信息，赋值到managerLoginVo对象。
            ManagerLoginVo managerLoginVo = new ManagerLoginVo();
            //利用工具类，进行复制
            BeanUtils.copyProperties(manager, managerLoginVo);

            //5、查询这个管理员用户的角色，根据角色id查询
            Role role = roleService.getById(manager.getRoleId());
            System.out.println("角色："+role);
            managerLoginVo.setRole(role);
            managerLoginVo.setRoleId(role.getId());

            //6、根据role_id查询当前角色对应的权限列表，并且复制给ManagerLoginVo对象的tree属性
            List<RuleBo> list = ruleService.getRuleListByRoleId(role.getId());//Alt+Enter键万能提示键
            //赋值给managerLoginVo的tree属性
            managerLoginVo.setTree(list);
            System.out.println("子菜单集合----》"+list);

            //7遍历权限菜单列表，取出所有的菜单名称，封装成新的列表，赋值给ManagerVo的ruleNames属性
            ArrayList<String> ruleNameList = new ArrayList<>();
            for (RuleBo ruleBo : list) {
                if (ruleBo.getRuleId()!=0)
                    ruleNameList.add(ruleBo.getName());
            }
            //把新的列表赋值给ManagerVo的ruleNames属性
            managerLoginVo.setRuleNames(ruleNameList);

            //8、颁发token
            //生成token
            String token = JwtUtils.getToken(manager.getId().longValue());
            //为当前用户颁发token
            managerLoginVo.setToken(token);


            //9、把token存入到Redis中
            Integer id = managerLoginVo.getId();
            //以字符的方式把当前登录的用户以JSON格式存入redis数据库
            redisTemplate.opsForValue().set("TOKEN:"+token, JSONUtils.toJSONString(id));


            return managerLoginVo;
        }
        return null;
    }

    /**
     * 分页查询
     *
     * @param page    从第n页开始
     * @param limit   到第n也结束
     * @param keyword 搜索的关键字
     * @return
     */
    @Override
    public ManagerPageVo findByPage(Integer page, Integer limit, String keyword) {
        //1.创建ManagerPageVo对象，后续的操作是向对象中属性进行赋值，最后将对象返回给Controller
        ManagerPageVo managerPageVo = new ManagerPageVo();
        //2.设置分页-PageHelper
        PageHelper.startPage(page,limit);
        //3.进行查询-查询管理员身份信息列表
        //3.1 查询管理员列表，且判断搜索关键字是否为null|""，如果是，就查询所有，不是就根据关键字进行查询
        // SELECT * FROM manager WHERE username LIKE keyword
        List<Manager> list = lambdaQuery().like(
                keyword != null || !keyword.equals(""),
                Manager::getUsername, keyword).list();
        //3.2 把查询到的数据封装到PageInfo对象里面，这样PageHelper就能自动的帮我们完成分页查询
        PageInfo<Manager> pageInfo=new PageInfo<>(list);
        List<ManagerVo> managerVoList = pageInfo.getList().stream().map(manager -> {
            ManagerVo managerVo = new ManagerVo();
            BeanUtils.copyProperties(manager,managerVo);
            //根据每个管理员的角色id查询角色
            Role role = roleService.getById(manager.getRoleId());
            managerVo.setRole(role);
            return managerVo;
        }).collect(Collectors.toList());
        //4.把分页查询并操作后得到的managerVoList集合放到managerPageVo里面
        managerPageVo.setList(managerVoList);
        //5.计算查询到的管理员列表长度
        managerPageVo.setTotalCount(pageInfo.getTotal());
        //6.查询角色列表，封装到managerPageVo里面
        List<RoleBo> roleBoList = roleService.list().stream().map(role -> {
            RoleBo roleBo = new RoleBo();
            BeanUtils.copyProperties(role, roleBo);
            return roleBo;
        }).collect(Collectors.toList());
        //7.把角色列表放到managerPageVo里面
        managerPageVo.setRole(roleBoList);
        //8.返回对象给Controller
        return managerPageVo;
    }
}
